<?php
/**
 * @link http://www.tintsoft.com/
 * @copyright Copyright (c) 2013 TintSoft LLC
 * @license http://www.tintsoft.com/license/
 */
namespace Leaps\Helper;
use FilesystemIterator;
use Leaps\Base\FileNotFoundException;
/**
 * BaseFileHelper 提供[[FileHelper]]具体的实现
 * 不要直接使用 BaseFileHelper. 使用 [[FileHelper]]
 *
 * @author Tongle Xu <xutongle@gmail.com>
 * @since 5.0
 */
class BaseFileHelper
{
	/**
     * 判断文件是否存在
     *
     * @param string $path
     * @return bool
     */
    public static function exists($path)
    {
        return file_exists ( $path );
    }

    /**
     * 获取文件内容
     *
     * @param string $path
     * @return string
     */
    public static function get($path)
    {
        if ( static::isFile ( $path ) ) return file_get_contents ( $path );
        throw new FileNotFoundException ( "File does not exist at path {$path}" );
    }

    /**
     * 获取远程文件的内容
     *
     * @param string $path
     * @return string
     */
    public static function getRemote($path)
    {
        return file_get_contents ( $path );
    }

    /**
     * 加载有返回值的文件
     *
     * @param string $path
     * @return mixed
     */
    public static function getRequire($path)
    {
        if ( static::isFile ( $path ) ) return require $path;
        throw new FileNotFoundException ( "File does not exist at path {$path}" );
    }

    /**
     * 加载指定的文件
     *
     * @param string $file
     * @return void
     */
    public static function requireOnce($file)
    {
        require_once $file;
    }

    /**
     * 向文件写入内容
     *
     * @param string $path 文件绝对路径
     * @param string $contents 内容
     * @return int
     */
    public static function put($path, $contents)
    {
        return file_put_contents ( $path, $contents );
    }

    /**
     * 追加内容到文件
     *
     * @param string $path 文件绝对路径
     * @param string $data 内容
     * @return int
     */
    public static function append($path, $data)
    {
        return file_put_contents ( $path, $data, FILE_APPEND );
    }

    /**
     * 删除文件
     *
     * @param string $path 文件绝对路径
     * @return bool
     */
    public static function delete($path)
    {
        return @unlink ( $path );
    }

    /**
     * 将一个文件移动到新的位置
     *
     * @param string $path
     * @param string $target
     * @return void
     */
    public static function move($path, $target)
    {
        return rename ( $path, $target );
    }

    /**
     * 复制文件到新路径
     *
     * @param string $path
     * @param string $target
     * @return void
     */
    public static function copy($path, $target)
    {
        return copy ( $path, $target );
    }

    /**
     * 从路径获取一个文件的扩展名
     *
     * @param string $path
     * @return string
     */
    public static function extension($path)
    {
        return pathinfo ( $path, PATHINFO_EXTENSION );
    }

    /**
     * 返回文件类型
     *
     * @param string $path
     * @return string
     */
    public static function type($path)
    {
        return filetype ( $path );
    }

    /**
     * 获取文件大小
     *
     * @param string $path
     * @return int
     */
    public static function size($path)
    {
        return filesize ( $path );
    }

    /**
     * Determines the MIME type of the specified file.
     * This method will first try to determine the MIME type based on
     * [finfo_open](http://php.net/manual/en/function.finfo-open.php). If this doesn't work, it will
     * fall back to [[getMimeTypeByExtension()]].
     * @param string $file the file name.
     * @param string $magicFile name of the optional magic database file, usually something like `/path/to/magic.mime`.
     * This will be passed as the second parameter to [finfo_open](http://php.net/manual/en/function.finfo-open.php).
     * @param boolean $checkExtension whether to use the file extension to determine the MIME type in case
     * `finfo_open()` cannot determine it.
     * @return string the MIME type (e.g. `text/plain`). Null is returned if the MIME type cannot be determined.
     */
    public static function getMimeType($file, $magicFile = null, $checkExtension = true)
    {
        if (function_exists('finfo_open')) {
            $info = finfo_open(FILEINFO_MIME_TYPE, $magicFile);
            if ($info) {
                $result = finfo_file($info, $file);
                finfo_close($info);
                if ($result !== false) {
                    return $result;
                }
            }
        }

        return $checkExtension ? static::getMimeTypeByExtension($file) : null;
    }

    /**
     * Determines the MIME type based on the extension name of the specified file.
     * This method will use a local map between extension names and MIME types.
     * @param string $file the file name.
     * @param string $magicFile the path of the file that contains all available MIME type information.
     * If this is not set, the default file aliased by `@Leaps/Base/mimeTypes.php` will be used.
     * @return string the MIME type. Null is returned if the MIME type cannot be determined.
     */
    public static function getMimeTypeByExtension($file, $magicFile = null)
    {
        static $mimeTypes = [];
        if ($magicFile === null) {
            $magicFile = __DIR__ . '/mimeType.php';
        }
        if (!isset($mimeTypes[$magicFile])) {
            $mimeTypes[$magicFile] = require($magicFile);
        }
        if (($ext = pathinfo($file, PATHINFO_EXTENSION)) !== '') {
            $ext = strtolower($ext);
            if (isset($mimeTypes[$magicFile][$ext])) {
                return $mimeTypes[$magicFile][$ext];
            }
        }
        return null;
    }

    /**
     * 获取文件的最后修改时间
     *
     * @param string $path
     * @return int
     */
    public static function lastModified($path)
    {
        return filemtime ( $path );
    }

    /**
     * 判断是否是一个目录
     *
     * @param string $directory
     * @return bool
     */
    public static function isDirectory($directory)
    {
        return is_dir ( $directory );
    }

    /**
     * 判断路径是否可写
     *
     * @param string $path
     * @return bool
     */
    public static function isWritable($path)
    {
        return is_writable ( $path );
    }

    /**
     * 确定给定的路径是否是一个文件。
     *
     * @param string $file
     * @return bool
     */
    public static function isFile($file)
    {
        return is_file ( $file );
    }

    /**
     * 找到一个给定的模式匹配的路径名称。
     *
     * @param string $pattern
     * @param int $flags
     * @return array
     */
    public static function glob($pattern, $flags = 0)
    {
        return glob ( $pattern, $flags );
    }

    /**
     * 得到一个阵列中的一个目录下的所有文件。
     *
     * @param string $directory
     * @return array
     */
    public static function files($directory)
    {
        $glob = glob ( $directory . '/*' );
        if ( $glob === false ) return array ();
        return array_filter ( $glob, function ($file)
        {
            return filetype ( $file ) == 'file';
        } );
    }

    /**
     * 递归创建文件夹
     *
     * @param string $path
     * @param int $mode
     * @param bool $recursive
     * @return bool
     */
    public static function createDirectory($path, $mode = 0777, $recursive = false)
    {
        if (is_dir($path)) {
            return true;
        }
        $parentDir = dirname($path);
        if ($recursive && !is_dir($parentDir)) {
            static::createDirectory($parentDir, $mode, true);
        }
        $result = mkdir($path, $mode);
        chmod($path, $mode);
        return $result;
    }

    /**
     * 从一个位置到另一个复制目录。
     *
     * @param string $directory
     * @param string $destination
     * @param int $options
     * @return void
     */
    public static function copyDirectory($directory, $destination, $options = null)
    {
        if ( ! static::iisDirectory ( $directory ) ) return false;
        if ( ! static::iisDirectory ( $destination ) ) {
            static::createDirectory ( $destination, 0777, true );
        }
        $options = $options ?  : FilesystemIterator::SKIP_DOTS;
        $items = new FilesystemIterator ( $directory, $options );
        foreach ( $items as $item ) {
            $target = $destination . '/' . $item->getBasename ();
            if ( $item->isDir () ) {
                $path = $item->getPathname ();
                if ( ! static::icopyDirectory ( $path, $target, $options ) ) return false;
            } else {
                if ( ! static::icopy ( $item->getPathname (), $target ) ) return false;
            }
        }
        return true;
    }

    /**
     * 递归删除一个目录。 The directory itself may be optionally preserved.
     *
     * @param string $directory
     * @param bool $preserve
     * @return void
     */
    public static function deleteDirectory($directory, $preserve = false)
    {
        if ( ! static::isDirectory ( $directory ) ) return;
        $items = new FilesystemIterator ( $directory );
        foreach ( $items as $item ) {
            if ( $item->isDir () ) {
                static::deleteDirectory ( $item->getPathname () );
            } else {
                static::delete ( $item->getPathname () );
            }
        }
        if ( ! $preserve ) @rmdir ( $directory );
    }

    /**
     * 清空指定目录下的所有文件和文件夹。
     *
     * @param string $directory
     * @return void
     */
    public static function cleanDirectory($directory)
    {
        return static::deleteDirectory ( $directory, true );
    }
}